package com.iceland.client.service;

import com.iceland.client.client.cmd.CmdClient;
import com.iceland.client.client.proxy.ProxyClient;
import com.iceland.common.rpc.RpcMessageManager;
import com.iceland.common.rpc.RpcServiceInterfaceFactory;
import com.iceland.common.service.server.RemoteServerService;
import com.iceland.common.thread.MessageEventExcutor;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ThreadPoolExecutor;

@Slf4j
public class StartProxyService {

    public static CmdClient startProxy(String realHost, int realPort, String proxyHost, int proxyPort, String cmdHost, int cmdPort) {
        ProxyClient proxyClient = new ProxyClient(realHost, realPort);
        CmdClient cmdClient = new CmdClient(proxyClient);
        ChannelFuture channelFuture = cmdClient.connectCmdServer(cmdHost + ":" + cmdPort);
        channelFuture.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                if (future.isSuccess()) {
                    RpcMessageManager rpcMessageManager = cmdClient.getRpcMessageManager();
                    RpcServiceInterfaceFactory rpcServiceInterfaceFactory = rpcMessageManager.getRpcServiceInterfaceFactory();
                    RemoteServerService remoteServerService = rpcServiceInterfaceFactory.getBean(RemoteServerService.class);
                    //使用线程调用远程方法，因为调用远程方法为阻塞同步的方式，当该方法在netty线程中调用时会导致读写线程被阻塞，无法接收远程方法调用返回的响应，导致死锁。（如在ChannelFuture中调用远程方法时）
                    ThreadPoolExecutor instance = MessageEventExcutor.getInstance();
                    instance.submit(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                int port = remoteServerService.startProxyServer(proxyPort);
                                log.info("成功启动代理服务器，本地端口{}映射到服务器端口{}",realPort,port);
                            } catch (Throwable e) {
                                log.error("启动代理服务器失败，{}",e.getMessage());
                            }

                        }
                    });
                }
            }
        });
        return cmdClient;
    }


}
